<?php
/**
 * Copyright (c) 2012, Jiehun.com.cn Inc. All Rights Reserved
 * @author zhanghaozheng@jiehun.com.cn
 * @date 2012-2-15
 * @version 1.0
 * @brief
 *
 **/
class Authnum { 
	//图片对象、宽度、高度、验证码长度 
	private $img; 
	private $img_width; 
	private $img_height; 
	private $len; 
	//随机字符串、y轴坐标值、随机颜色 
	private $randnum; 
	private $y; 
	private $randcolor; 
	//背景色的红绿蓝，默认是浅灰色 
	public $red=238; 
	public $green=238; 
	public $blue=238; 
	private $font;        //指定的字体  
	private $fontsize = 14; //指定字体大小  
	private $fontcolor;
	  
	/** 
	 * 可选设置：验证码类型、干扰点、干扰线、Y轴随机 
	 * 设为 false 表示不启用 
	 **/ 
	//默认是大小写数字混合型，1 2 3 分别表示 小写、大写、数字型 
	public $ext_num_type=''; 
	public $ext_pixel = false; //干扰点 
	public $ext_line = false; //干扰线 
	public $ext_rand_y= true; //Y轴随机 
	
	
	function __construct ($len=4,$im_height=25) { 
		// 验证码长度、图片宽度、高度是实例化类时必需的数据 
		$this->len = $len;
	    $im_width = $len * 15; 
		$this->img_width = $im_width; 
		$this->img_height= $im_height; 
		$this->img = imagecreate($im_width,$im_height); 
		$this->ext_num_type=''; 
		$this->ext_pixel = true; //干扰点 
		$this->ext_line = true; //干扰线 
		$this->ext_rand_y= true; //Y轴随机 
	} 
	// 设置图片背景颜色，默认是浅灰色背景 
	function setBGColor () { 
		imagecolorallocate($this->img,$this->red,$this->green,$this->blue); 
	} 
	// 获得任意位数的随机码 
	function getRandnum () { 
		$randnum = '';
		$an1 = 'abcdefghkmnpstuwxy'; 
		$an2 = 'ABCDEFGHJKMNPSTUWXY'; 
		$an3 = '23456789'; 
		if ($this->ext_num_type == '') $str = $an1.$an2.$an3; 
		if ($this->ext_num_type == 1) $str = $an1; 
		if ($this->ext_num_type == 2) $str = $an2; 
		if ($this->ext_num_type == 3) $str = $an3; 
		for ($i = 0; $i < $this->len; $i++) { 
			$start = rand(1,strlen($str) - 1); 
			$randnum .= substr($str,$start,1); 
		} 
		$this->randnum = $randnum; 
		return $randnum;
	} 
	// 获得验证码图片Y轴 
	function getY () { 
		if ($this->ext_rand_y) $this->y = rand(5, $this->img_height/5); 
		else $this->y = $this->img_height / 4 ; 
	} 
	// 获得随机色 
	function getRandColor () { 
		$this->randcolor = imagecolorallocate($this->img,rand(0,100),rand(0,150),rand(0,200)); 
	} 
	// 添加干扰点 
	function setExtPixel () { 
		if ($this->ext_pixel) { 
			for($i = 0; $i < 100; $i++){ 
				$this->getRandColor(); 
				imagesetpixel($this->img, rand()%100, rand()%100, $this->randcolor); 
			} 
		} 
	} 
	// 添加干扰线 
	function setExtLine () { 
		if ($this->ext_line) { 
			$h = $this->img_height;
			$w = $this->img_width;
			$h1=rand(-5,5);
			$h2=rand(-1,1);
			$w2=rand(10,15);
			$h3=rand(4,6);
			$this->getRandColor(); 
			for($i=-$w/2;$i<$w/2;$i=$i+0.1)
			{
				$y=$h/$h3*sin($i/$w2)+$h/2+$h1;
				imagesetpixel($this->img,$i+$w/2,$y,$this->randcolor);
				$h2!=0?imagesetpixel($this->img,$i+$w/2,$y+$h2,$this->randcolor):null;
			}
		} 
	
	} 
	
	function setExtFont() {   
		$basex = 5;//距左边距
		$TPadden = 0.8;//字间距
		$_x = ($this->img_width-10) / $this->len;  
		for ($i=0;$i<$this->len;$i++) {
			$char = $this->randnum[$i];
			$ttf = (empty($ttf)) ? rand(2,6) : rand(1,6);
			$this->font = LIB_ROOT."fonts/".$ttf.".ttf";
			$this->fontcolor = imagecolorallocate($this->img,rand(0,136),rand(0,136),rand(0,136)); 
			$angle = (empty($angle)) ? mt_rand(-40,40) :( ($angle<0) ? mt_rand(0,40) : mt_rand(-40,0)) ; ///旋转角度
			$fontsize = ($ttf==4 || $ttf==1) ? $this->fontsize + 2 : $this->fontsize ; ///字体大小
			$bound=$this->_calculateTextBox($fontsize,$angle,$this->font,$char); ///得到范围
			imagettftext($this->img,$fontsize,$angle,$basex,$bound['top'],$this->fontcolor,$this->font,$char);  
			$basex = $basex+$bound['width']*$TPadden-$bound['left'];///计算下一个左边距
		}
	}  
	/**创建验证码图像： 
	 * 建立画布（__construct函数） 
	 * 设置画布背景（$this->setBGColor();） 
	 * 获取随机字符串（$this->getRandnum ();） 
	 * 文字写到图片上（imagestring函数） 
	 * 添加干扰点/线（$this->setExtLine(); $this->setExtPixel();） 
	 * 输出图片 
	 **/ 
	function create2 ($randnum , $im_width=false , $im_height=false ,$fontsize=false) { 
		$this->img_width = ($im_width) ? $im_width : $this->img_width; 
		$this->img_height = ($im_height) ? $im_height : $this->img_height; 
		$this->img = imagecreate($im_width,$im_height); 
		$this->fontsize = ($fontsize) ? $fontsize : $this->fontsize; 
		$this->setBGColor(); 
		$this->setExtFont(); 
		$this->setExtLine(); 
		$this->setExtPixel(); 
		imagepng($this->img); 
		imagedestroy($this->img); //释放图像资源 
	} 
   	function create ($randnum) {
         $this->setBGColor();
         for($i = 0; $i < $this->len; $i++){
             $x = $i/$this->len * $this->img_width + rand(1, $this->len);
             $this->getY();
             $this->getRandColor();
             imagestring($this->img, 6, $x, $this->y, substr($randnum, $i ,1), $this->randcolor);
         }
         $this->setExtLine();
         $this->setExtPixel();
         imagepng($this->img);
         imagedestroy($this->img); //释放图像资源 
     }

	/**
	 *通过字体角度得到字体矩形宽度*
	 *
	 * @param int $font_size 字体尺寸
	 * @param float $font_angle 旋转角度
	 * @param string $font_file 字体文件路径
	 * @param string $text 写入字符
	 * @return array 返回长宽高
	 */
	private function _calculateTextBox($font_size, $font_angle, $font_file, $text) {
		$box = imagettfbbox($font_size, $font_angle, $font_file, $text);

		$min_x = min(array($box[0], $box[2], $box[4], $box[6]));
		$max_x = max(array($box[0], $box[2], $box[4], $box[6]));
		$min_y = min(array($box[1], $box[3], $box[5], $box[7]));
		$max_y = max(array($box[1], $box[3], $box[5], $box[7]));

		return array(
		'left' => ($min_x >= -1) ? -abs($min_x + 1) : abs($min_x + 2),
		'top' => abs($min_y),
		'width' => $max_x - $min_x,
		'height' => $max_y - $min_y,
		'box' => $box
		);
	}
	
}
